package com.ling.fireworks.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

/**
 * author:17873
 * date:2024/4/4
 * des:BaseViewModel
 **/
abstract class IViewModel<UiIntent : IUiIntent, UiState : IUiState, UiEvent : IUiEvent> : ViewModel(){

    private val uiIntent by lazy { Channel<UiIntent>(Channel.UNLIMITED) }
    private val uiAction by lazy { MutableSharedFlow<UiEvent>() }
    //对内提供
    private val _uiState by lazy {
        val iState = initUiState()
        if(iState == null) null else MutableStateFlow(iState)
    }
    //对外提供
    val uiState by lazy { _uiState!!.asStateFlow() }

    init {
        viewModelScope.launch {
            uiIntent
                .receiveAsFlow()
                .collect{ intent ->
                    handleIntent(intent)
                }
        }
    }

    //创建Ui状态
    protected open fun initUiState():UiState?{
        return null
    }

    //处理UI意图
    protected abstract fun handleIntent(intent: UiIntent)

    //发送UI一次性事件
    protected suspend fun sendUiEvent(ac: UiEvent){
        uiAction.emit(ac)
    }

    //更新View状态
    protected fun updateUiState(copy : UiState.() -> UiState){
        _uiState?.let { ui->
            ui.update {
                copy(ui.value)
            }
        }
    }

    //发送ui意图
    fun sendUiIntent(intent: UiIntent){
        viewModelScope.launch {
            uiIntent.send(intent)
        }
    }

    /**
    * 相应UI一次性事件，例如弹窗、Toast
    * */
    fun handleUiEvent(onUiEvent : (uiEvent : UiEvent) -> Unit){
        //distinctUntilChanged 去重
        viewModelScope.launch {
            uiAction.collect{
                onUiEvent(it)
            }
        }
    }

    override fun onCleared() {
        super.onCleared()
        uiIntent.close()
    }
}